home *** CD-ROM | disk | FTP | other *** search
- /*
- ** dither - Dither a 24-bit color image to an 8 bit mapped image.
- **
- ** Jack Jansen, CWI, 1995.
- **
- ** Modified from ppmquant.c, which is
- ** Copyright (C) 1989, 1991 by Jef Poskanzer.
- **
- ** Permission to use, copy, modify, and distribute this software and its
- ** documentation for any purpose and without fee is hereby granted, provided
- ** that the above copyright notice appear in all copies and that both that
- ** copyright notice and this permission notice appear in supporting
- ** documentation. This software is provided "as is" without express or
- ** implied warranty.
- */
-
- #include "Python.h"
- #include "mppmcmap.h"
-
- #define MAXCOLORS 32767
-
- int
- mppm_dither(pixels, cols, rows, colormap, newcolors, floyd, result)
- pixel *pixels;
- int cols, rows;
- pixel *colormap;
- int newcolors;
- int floyd;
- unsigned char *result;
- {
- #if 0
- int
- main( argc, argv )
- int argc;
- char* argv[];
- {
- FILE* ifp;
- pixel** pixels;
- pixel** mappixels;
- register pixel* pP;
- int argn, rows, cols, maprows, mapcols, row;
- register int col, limitcol;
- pixval maxval, newmaxval, mapmaxval;
- int newcolors, colors;
- register int ind;
- colorhist_vector chv, colormap;
- int floyd;
- char* usage = "[-floyd|-fs] <ncolors> [ppmfile]\n [-floyd|-fs] -map mapfile [ppmfile]";
- #endif
- colorhash_table cht;
- int usehash;
- long thispixel;
- int ind;
- long* thisrerr;
- long* nextrerr;
- long* thisgerr;
- long* nextgerr;
- long* thisberr;
- long* nextberr;
- long* temperr;
- register long sr, sg, sb, err;
- #define FS_SCALE 1024
- int fs_direction;
- int col, limitcol, row;
- register pixel* pP;
-
- /*
- ** Step 4: map the colors in the image to their closest match in the
- ** new colormap, and write 'em out.
- */
- cht = mppm_alloccolorhash( );
- usehash = 1;
- if ( floyd )
- {
- /* Initialize Floyd-Steinberg error vectors. */
- thisrerr = (long*) calloc( cols + 2, sizeof(long) );
- nextrerr = (long*) calloc( cols + 2, sizeof(long) );
- thisgerr = (long*) calloc( cols + 2, sizeof(long) );
- nextgerr = (long*) calloc( cols + 2, sizeof(long) );
- thisberr = (long*) calloc( cols + 2, sizeof(long) );
- nextberr = (long*) calloc( cols + 2, sizeof(long) );
- if ( !thisrerr || !nextrerr || !thisgerr ||
- !nextgerr || !thisberr || !nextberr )
- return -1;
- #ifdef macintosh
- srand(time(0));
- #else
- srand( (int) ( time( 0 ) ^ getpid( ) ) );
- #endif
- for ( col = 0; col < cols + 2; ++col )
- {
- thisrerr[col] = rand( ) % ( FS_SCALE * 2 ) - FS_SCALE;
- thisgerr[col] = rand( ) % ( FS_SCALE * 2 ) - FS_SCALE;
- thisberr[col] = rand( ) % ( FS_SCALE * 2 ) - FS_SCALE;
- /* (random errors in [-1 .. 1]) */
- }
- fs_direction = 1;
- }
- for ( row = 0; row < rows; ++row )
- {
- if ( floyd )
- for ( col = 0; col < cols + 2; ++col )
- nextrerr[col] = nextgerr[col] = nextberr[col] = 0;
- if ( ( ! floyd ) || fs_direction )
- {
- col = 0;
- limitcol = cols;
- pP = &pixels[row*cols];
- }
- else
- {
- col = cols - 1;
- limitcol = -1;
- pP = &(pixels[row*cols+col]);
- }
- do
- {
- if ( floyd )
- {
- /* Use Floyd-Steinberg errors to adjust actual color. */
- sr = MPPM_GETR(*pP) + thisrerr[col + 1] / FS_SCALE;
- sg = MPPM_GETG(*pP) + thisgerr[col + 1] / FS_SCALE;
- sb = MPPM_GETB(*pP) + thisberr[col + 1] / FS_SCALE;
- if ( sr < 0 ) sr = 0;
- else if ( sr > MAXVAL ) sr = MAXVAL;
- if ( sg < 0 ) sg = 0;
- else if ( sg > MAXVAL ) sg = MAXVAL;
- if ( sb < 0 ) sb = 0;
- else if ( sb > MAXVAL ) sb = MAXVAL;
- MPPM_ASSIGN( thispixel, sr, sg, sb );
- } else {
- thispixel = *pP;
- }
-
- /* Check hash table to see if we have already matched this color. */
- ind = mppm_lookupcolor( cht, &thispixel );
- if ( ind == -1 )
- { /* No; search colormap for closest match. */
- register int i, r1, g1, b1, r2, g2, b2;
- register long dist, newdist;
- r1 = MPPM_GETR( thispixel );
- g1 = MPPM_GETG( thispixel );
- b1 = MPPM_GETB( thispixel );
- dist = 2000000000;
- for ( i = 0; i < newcolors; ++i )
- {
- r2 = MPPM_GETR( colormap[i] );
- g2 = MPPM_GETG( colormap[i] );
- b2 = MPPM_GETB( colormap[i] );
- newdist = ( r1 - r2 ) * ( r1 - r2 ) +
- ( g1 - g2 ) * ( g1 - g2 ) +
- ( b1 - b2 ) * ( b1 - b2 );
- if ( newdist < dist )
- {
- ind = i;
- dist = newdist;
- }
- }
- if ( usehash )
- {
- if ( mppm_addtocolorhash( cht, &thispixel, ind ) < 0 )
- {
- pm_message(
- "out of memory adding to hash table, proceeding without it");
- usehash = 0;
- }
- }
- }
-
- if ( floyd )
- {
- /* Propagate Floyd-Steinberg error terms. */
- if ( fs_direction )
- {
- err = ( sr - (long) MPPM_GETR( colormap[ind] ) ) * FS_SCALE;
- thisrerr[col + 2] += ( err * 7 ) / 16;
- nextrerr[col ] += ( err * 3 ) / 16;
- nextrerr[col + 1] += ( err * 5 ) / 16;
- nextrerr[col + 2] += ( err ) / 16;
- err = ( sg - (long) MPPM_GETG( colormap[ind] ) ) * FS_SCALE;
- thisgerr[col + 2] += ( err * 7 ) / 16;
- nextgerr[col ] += ( err * 3 ) / 16;
- nextgerr[col + 1] += ( err * 5 ) / 16;
- nextgerr[col + 2] += ( err ) / 16;
- err = ( sb - (long) MPPM_GETB( colormap[ind] ) ) * FS_SCALE;
- thisberr[col + 2] += ( err * 7 ) / 16;
- nextberr[col ] += ( err * 3 ) / 16;
- nextberr[col + 1] += ( err * 5 ) / 16;
- nextberr[col + 2] += ( err ) / 16;
- }
- else
- {
- err = ( sr - (long) MPPM_GETR( colormap[ind] ) ) * FS_SCALE;
- thisrerr[col ] += ( err * 7 ) / 16;
- nextrerr[col + 2] += ( err * 3 ) / 16;
- nextrerr[col + 1] += ( err * 5 ) / 16;
- nextrerr[col ] += ( err ) / 16;
- err = ( sg - (long) MPPM_GETG( colormap[ind] ) ) * FS_SCALE;
- thisgerr[col ] += ( err * 7 ) / 16;
- nextgerr[col + 2] += ( err * 3 ) / 16;
- nextgerr[col + 1] += ( err * 5 ) / 16;
- nextgerr[col ] += ( err ) / 16;
- err = ( sb - (long) MPPM_GETB( colormap[ind] ) ) * FS_SCALE;
- thisberr[col ] += ( err * 7 ) / 16;
- nextberr[col + 2] += ( err * 3 ) / 16;
- nextberr[col + 1] += ( err * 5 ) / 16;
- nextberr[col ] += ( err ) / 16;
- }
- }
-
- /* XXXX *pP = colormap[ind].color; */
- result[col] = ind;
-
- if ( ( ! floyd ) || fs_direction )
- {
- ++col;
- ++pP;
- }
- else
- {
- --col;
- --pP;
- }
- }
- while ( col != limitcol );
-
- if ( floyd )
- {
- temperr = thisrerr;
- thisrerr = nextrerr;
- nextrerr = temperr;
- temperr = thisgerr;
- thisgerr = nextgerr;
- nextgerr = temperr;
- temperr = thisberr;
- thisberr = nextberr;
- nextberr = temperr;
- fs_direction = ! fs_direction;
- }
-
- /*XXXX mppm_writeppmrow( stdout, pixels[row], cols, MAXVAL, 0 ); */
- result += cols;
- }
- /* XXXX Free temp data XXXX */
- return 0;
- }
-